---------------------------------------------------------------------------------------------------- -- Szinkronfeliratok ---------------------------------------------------------------------------------------------------- -- Készítette: ·f·i· csoport -- Mr. Fusion (mrf_of_vsb@hotmail.com) -- The Sweet Little 16-bit (tsl16b@freemail.hu) -- edited: Alundaio 11/23/2013 ---------------------------------------------------------------------------------------------------- -- caption type override table -- snd_id = {cc_type, showtime, sendericon, faction, name, distance_limit} -- cc_type = -1: incoming message, -2: memo, -3: sending message, -4: (none) local snd_ids = { ["cc_effect-device-door_start"] = {9, 1500, nil, nil, nil, 20}, ["cc_effect-device-door_closing"] = {9, 1500, nil, nil, nil, 20}, ["cc_effect-device-door_stop"] = {9, 1500, nil, nil, nil, 20}, ["cc_effect-device-metal_small_open"] = {9, 1500, nil, nil, nil, 15}, ["cc_effect-device-power_switch"] = {9, 1500}, ["cc_effect-device-radio_call"] = {9, 2500}, ["cc_effect-device-wood_large_open"] = {9, 1500, nil, nil, nil, 10}, ["cc_effect-device-wood_large_close_start"] = {9, 1500, nil, nil, nil, 10}, ["cc_effect-ambient-blowout_begin"] = {9, 2500}, ["cc_effect-anomaly-steam_blowout"] = {9, nil, nil, nil, nil, 25}, ["cc_effect-weapons-n_desert_eagle_shot"] = {9, 1000, nil, nil, nil, 30}, -- scene triggered at around 25m ["cc_effect-music-guitar_"] = {9, 3500, nil, nil, nil, 15}, ["cc_effect-music-harmonica_"] = {9, 3500, nil, nil, nil, 15}, ["cc_effect-laughter_"] = {9, 2500, nil, nil, nil, 15}, ["cc_effect-ambient-zaton-zat_b38_bloodsucker_roar"] = {6, 3500}, ["cc_effect-ambient-zaton-zat_b38_electro_box_door"] = {9, 1500}, ["cc_effect-ambient-zaton-zat_b38_electro_box_switch"] = {9, 1500}, ["cc_effect-ambient-zaton-zat_b38_elevator_door"] = {9}, ["cc_effect-ambient-zaton-zat_b38_cop_elevator_landing"] = {9}, ["cc_effect-ambient-zaton-zat_b38_lock_sound"] = {9}, ["cc_effect-ambient-zaton-zat_b57_bloodsucker_roar"] = {6, 3500}, ["cc_effect-ambient-jupiter-jup_b16_oasis_noise"] = {9, 1250}, ["cc_effect-ambient-jupiter-jup_b41_steam"] = {9}, ["cc_effect-ambient-jupiter-jup_b46_spatial_bubble_idle"] = {9}, ["cc_effect-ambient-jupiter-jup_b46_spatial_bubble_rupture"] = {9}, ["cc_effect-ambient-jupiter-jup_b219_generator_start"] = {9, 2500}, ["cc_effect-ambient-jupiter-jup_b219_underpass_opening"] = {9, 4000}, ["cc_effect-ambient-underpass-pas_b400_elevator_off"] = {9}, ["cc_effect-ambient-pripyat-pri_a25_blow_up_door_peep"] = {9, 4000}, ["cc_effect-ambient-pripyat-pri_a25_freezer_knock"] = {9, 1800, nil, nil, nil, 14}, -- ***** Zaton ***** --- Skadovsk announcements ["zat_a2_base_megaphone_1"] = {8}, ["zat_a2_base_megaphone_2"] = {8}, ["zat_a2_base_megaphone_3"] = {8}, ["zat_a2_stalker_barmen_surge_phase_1"] = {-1, nil, "ui_inGame2_Boroda", "stalker", "zat_a2_stalker_barmen_name"}, -- actor override ["zat_a2_stalker_barmen_surge_phase_2"] = {-1, nil, "ui_inGame2_Boroda", "stalker", "zat_a2_stalker_barmen_name"}, -- actor override ["zat_a2_stalker_barmen_after_surge"] = {-1, nil, "ui_inGame2_Boroda", "stalker", "zat_a2_stalker_barmen_name"}, -- actor override --- Order ready at Nimble (actor override) ["zat_b51_stalker_nimble_order"] = {-1, nil, "ui_inGame2_neutral_1", "stalker", "st_zat_a2_stalker_nimble_name"}, -- ***** Jupiter ***** --- Janov announcements ["jup_a6_base_megaphone_1"] = {8}, ["jup_a6_base_megaphone_2"] = {8}, ["jup_a6_base_megaphone_3"] = {8}, ["jup_a6_stalker_medik_phase_1"] = {-1, nil, "ui_inGame2_Kostoprav", "stalker", "jup_a6_stalker_medik"}, -- actor override ["jup_a6_stalker_medik_phase_2"] = {-1, nil, "ui_inGame2_Kostoprav", "stalker", "jup_a6_stalker_medik"}, -- actor override ["jup_a6_stalker_medik_after_surge"] = {-1, nil, "ui_inGame2_Kostoprav", "stalker", "jup_a6_stalker_medik"}, -- actor override --- Sci bunker announcements ["jup_b41_bunker_megaphone_1"] = {8}, ["jup_b41_bunker_megaphone_2"] = {8}, ["jup_b41_bunker_megaphone_3"] = {8}, --- Anomaly measurement sequence (actor override) ["jup_b6_stalker_1_first_measurement_in_progress"] = {-1, 3000, "ui_inGame2_neutral_2", "stalker", ""}, ["jup_b6_stalker_1_first_measurement_done"] = {-1, 5000, "ui_inGame2_neutral_2", "stalker", ""}, ["jup_b6_stalker_1_measurements_done"] = {-1, 3500, "ui_inGame2_neutral_2", "stalker", ""}, -- ***** Underpass ***** -- ***** Pripyat ***** --- Army base announcements ["pri_a17_kovalsky_surge_phase_1"] = {-1, nil, "ui_inGame2_Kovalskiy", "army", "pri_a17_military_colonel_kovalski_name"}, -- actor override ["pri_a17_kovalsky_surge_phase_2"] = {-1, nil, "ui_inGame2_Kovalskiy", "army", "pri_a17_military_colonel_kovalski_name"}, -- actor override ["pri_a17_kovalsky_after_surge"] = {-1, nil, "ui_inGame2_Kovalskiy", "army", "pri_a17_military_colonel_kovalski_name"}, -- actor override } local snd_groups = { ["cc_fight"] = {6, 1250, nil, nil, nil, 50}, ["cc_wounded"] = {9, 2500, nil, nil, nil, 35}, } local last_caption_category = "" local longest_caption_ends = 0 local delayed_cc = {} function sound(_sound, showtime, sender, sender_faction, sender_id, delay_sound) local cc = ui_options.get("sound/general/caption") local cc_npc = (cc == "storyonly") or (cc == "all") or false local cc_vrb = (cc == "all") or false local cc_icc = cc_npc and true or false if cc_npc == true then local current_time = time_global() local split_sound_string = {} local i = 1 for w in string.gmatch(_sound, "[%w_]+") do split_sound_string[i] = w i = i + 1 end local cc_id, cc_category if split_sound_string[1] == "characters_voice" then if split_sound_string[2] == "scenario" then if not cc_vrb then if string.match(split_sound_string[4], "_greeting_%d") or string.match(split_sound_string[4], "_farewell_") then return true end end cc_category = "cc_scenario" cc_id = split_sound_string[4] elseif string.match(split_sound_string[2], "human_0") then if split_sound_string[4] == "states" then if split_sound_string[5] == "meet" then if (current_time > longest_caption_ends) or (last_caption_category ~= "cc_scenario") then if string.match(split_sound_string[6], "meet_use") then if #delayed_cc >= 1 then if delay_sound < 0 then delay_sound = -delay_sound - 501 end else local gt = time_global() + 500 delayed_cc[#delayed_cc+1] = {_sound, showtime, sender, sender_faction, sender_id, -delay_sound - 1, dt = gt} RegisterScriptCallback("actor_on_update", on_actor_update_cc) return true end else if not cc_vrb then return true end end if db.actor:is_talking() then return true end cc_category = "cc_generic" cc_id = cc_category .. "-" .. split_sound_string[3] .. "-" .. split_sound_string[6] else return true end else return false end elseif split_sound_string[4] == "reactions" then if split_sound_string[5] == "story" then if cc_icc then cc_category = "cc_effect" cc_id = cc_category .. "-" .. split_sound_string[6] cc_id = string.gsub(cc_id, "_%d+$", "_") else return true end else return false end elseif split_sound_string[4] == "help" then if split_sound_string[5] == "wounded_heavy" then if cc_icc then cc_category = "cc_wounded" cc_id = cc_category .. "-" .. split_sound_string[3] .. "-" .. "help" else return true end else return false end elseif split_sound_string[4] == "fight" then if split_sound_string[5] == "attack" then if cc_icc then cc_category = "cc_fight" cc_id = cc_category .. "-" .. split_sound_string[3] .. "-" .. "attack" else return true end else return false end else -- add any special "human_0x" cases here if string.match(split_sound_string[#split_sound_string], "pas_b400_") then cc_category = "cc_scenario" cc_id = split_sound_string[#split_sound_string] else return false end end else return false end elseif split_sound_string[1] == "device" or split_sound_string[1] == "ambient" then if cc_icc then cc_category = "cc_effect" cc_id = cc_category for i = 1, #split_sound_string do cc_id = cc_id .. "-" .. split_sound_string[i] end else return true end elseif split_sound_string[1] == "music" then if cc_icc then cc_category = "cc_effect" cc_id = cc_category for i = 1, #split_sound_string do cc_id = cc_id .. "-" .. split_sound_string[i] end cc_id = string.gsub(cc_id, "_%d+$", "_") else return true end else -- add any special full soundpath match cases here if _sound == "anomaly\\steam_blowout" then if cc_icc then cc_category = "cc_effect" cc_id = cc_category .. "-anomaly-steam_blowout" else return true end elseif _sound == "weapons\\n_desert_eagle_shot" then if cc_icc then cc_category = "cc_effect" cc_id = cc_category .. "-weapons-n_desert_eagle_shot" else return true end else return false end end local cc_text = game.translate_string(cc_id) if cc_text == cc_id then cc_text = "[...]" -- if (DEV_DEBUG) then -- printf("Missing CC: %s",cc_id) -- end else local distance_limit = 10001 local cc_type if sender_faction == "object" then cc_type = 9 else cc_type = -1 end if not showtime then showtime = 5000 elseif showtime < 2000 then showtime = 2000 end if not delay_sound then delay_sound = 0 end local override if snd_ids[cc_id] then override = snd_ids[cc_id] elseif snd_groups[cc_category] then override = snd_groups[cc_category] end if override then if override[1] then cc_type = override[1] end if override[2] then showtime = override[2] end if override[3] then sender = override[3] end if override[4] then sender_faction = override[4] end if override[5] then sender_id = override[5] end if override[6] then distance_limit = override[6] end end if cc_type == "t" then cc_display_tutorial(cc_id) return true elseif cc_type > 0 then if type(sender) == "userdata" then if distance_between_safe(sender, db.actor) < distance_limit then cc_display_normal(cc_id, showtime, cc_type) end else cc_display_normal(cc_id, showtime, cc_type) end return true else if type(sender) == "userdata" then local distance = distance_between_safe(sender, db.actor) if distance < distance_limit then if cc_type == -1 and distance < 12 then cc_type = -4 end else return true end end cc_display_radio(sender, sender_faction, sender_id, showtime, cc_text, delay_sound, cc_type) last_caption_category = cc_category if current_time + showtime + delay_sound + 1000 > longest_caption_ends then longest_caption_ends = current_time + showtime + delay_sound + 1000 end return true end end end end local colors = { [1] = "closecaption_1", [2] = "closecaption_2", [3] = "closecaption_3", [4] = "closecaption_4", [5] = "cs_subtitles_npc", [6] = "closecaption_6", [7] = "cs_subtitles_actor", [8] = "cs_subtitles_object", [9] = "closecaption_9", [10] = "cs_subtitles", } local cc_on = {0, 0, 0, 0} function cc_display_normal(cc_id, showtime, color) local time_now = time_global() local time_ccend = (time_now + showtime + 300) / 1000 if color == 0 then for i,v in ipairs(cc_on) do if v <= time_now then color = i break end end if color == 0 then color = 1 end end local tmpl = colors[color] local tmpls = tmpl .. "_shadow" local hud = get_hud() if (hud) then hud:AddCustomStatic(tmpls, true) local custom_static_shadow = hud:GetCustomStatic(tmpls) hud:AddCustomStatic(tmpl, true) local custom_static = hud:GetCustomStatic(tmpl) if custom_static_shadow ~= nil then custom_static_shadow:wnd():TextControl():SetTextST(cc_id) custom_static_shadow.m_endTime = time_ccend end if custom_static ~= nil then custom_static:wnd():TextControl():SetTextST(cc_id) custom_static.m_endTime = time_ccend end if color <= #cc_on then cc_on[color] = time_ccend * 1000 end end end local msgtypes = {"st_tip", "st_memo", "st_sending_msg", ""} function cc_display_radio(sender, sender_faction, sender_id, showtime, cc_text, delay_sound, cc_type) local msg_type = msgtypes[-cc_type] local texture, faction, name if (type(sender) == "userdata" and IsStalker(sender) and sender:id() ~= 0) then texture = sender:character_icon() if sender:profile_name() ~= "actor" then faction = game.translate_string(sender:character_community()) end name = sender:character_name() elseif type(sender) == "table" then texture = string.sub(sender[math.random(1, #sender)], 1) end if sender_faction then faction = game.translate_string(sender_faction) end if sender_id then if sender_id == "!" then name = sender_unidentified() else name = game.translate_string(sender_id) end end local news_caption = "" if msg_type and msg_type ~= "" then news_caption = game.translate_string(msg_type) end if faction and faction ~= "" then if news_caption ~= "" then news_caption = news_caption .. " - " .. faction else news_caption = faction end end if name and name ~= "" then if news_caption ~= "" then news_caption = news_caption .. " - " .. name else news_caption = name end end if news_caption ~= "" then news_caption = news_caption..":" end local clr = "%c[ui_2]" db.actor:give_game_news(news_caption, clr .. cc_text, texture, delay_sound+500, showtime, 1) return true end function cc_display_tutorial(cc_id) local running = game.has_active_tutorial() if running == false then game.start_tutorial(cc_id) end end function read_cc_ini() -------- Read values for closecaptions local cc_npc, cc_vrb, cc_icc = false, false, false cc_npc = load_var("cc_npc", 0) if cc_npc == 0 then local cc = ui_options.get("sound/general/caption") cc_npc = (cc == "storyonly") or (cc == "all") or false cc_vrb = (cc == "all") or false cc_icc = cc_npc and true or false db.cc_npc = cc_npc db.cc_vrb = cc_vrb db.cc_icc = cc_icc save_var("cc_icc", cc_icc) save_var("cc_vrb", cc_icc) save_var("cc_npc", cc_npc) else cc_vrb = load_var("cc_vrb", cc_vrb) cc_icc = load_var("cc_icc", cc_icc) db.cc_npc = cc_npc db.cc_vrb = cc_vrb db.cc_icc = cc_icc end end function on_actor_update_cc() if #delayed_cc >= 1 then if time_global() >= delayed_cc[1].dt then local d = delayed_cc[1] closecaption.sound(d[1], d[2], d[3], d[4], d[5], d[6]) table.remove(delayed_cc, 1) end else UnregisterScriptCallback("actor_on_update", on_actor_update_cc) end end -- Preconditions for SSU communication scene of STALKER: Call Of Pripyat function both_heli_info() return has_alife_info("zat_b101_both_heli_info") and db.cc_npc == true end function not_both_heli_info() return (not has_alife_info("zat_b101_both_heli_info")) and db.cc_npc == true end function cc_npc_disabled() return (ui_options.get("sound/general/caption") == "none") end function is_cc_npc_enabled() return (ui_options.get("sound/general/caption") ~= "none") end function get_game_version() -- detect real game version local ver = 1600 if dialogs_jupiter.zat_b106_trapper_reward ~= nil then -- v1.6.01 addition local GSver = _G.main_menu.get_main_menu():GetGSVer() ver = tonumber((string.gsub(GSver, "%p", ""))) if (ver == nil) or (ver < 1600) then ver = 1601 end end return ver end function sender_unidentified() local senders = { "", -- a couple of random chars from charset below "st_msgfrom_err1", -- "[sender unknown]" "st_msgfrom_err2", -- "" "st_msgfrom_err3", -- "=?Network failure" "st_msgfrom_err1", -- "[sender unknown]" "", -- a couple of random chars from charset below } msg = senders[math.random(1, #senders)] if msg ~= "" then return game.translate_string(msg) else local length = 7 + math.random(1, 7) local charset = "@AÁBCDEÉFGHIÍJKLMNOÓÖÕPQRSTUÚÜÛVWXYZ" .. "`aábcdeéfghiíjklmnoóöõpqrstuúüûvwxyz" .. [[!"#&'()*+,-./0123456789:;<=>?^_{|}]] .. "~€‚„…‰ŒŽ‘’“”•–—™žŸ¡¢£¥§¨©ª«­®¯°±²³´µ" .. "¶·¸¹º»¼½¾¿ÀÂÃÄÅÆÇÈÊËÌÎÏÐÑÒÔרÙÝÞßàâã" .. "äåæçèêëìîïðñòô÷øùýþÿ" local result = {} for i = 1, length do local r = math.random(1, charset:len()) result[i] = string.sub(charset, r, r) end return table.concat(result) end end -- Code portions from the excellent AMK mod -- function del_variable(variable_name) if db.storage[AC_ID].pstor[variable_name] then db.storage[AC_ID].pstor[variable_name] = nil end end ----------------------------------------------